"""
@author:王耀
@date:2021/9/17
"""

import cv2
import numpy as np
import math
from gauss import GaussFilter
from gray import Gray
import sobel
import NMS
import adaptivemidfilter
import bilateralfilter

def Canny(img, is_bilateral = 0, is_medium = 0, gausssize=3, gausssigma = 0.01, bilateral_size = 9, bilateral_dsigma = 0.01,
          bilateral_rsigma = 0.03,
          sobel_direct = 2, thres1 = None, thres2 = None, otsu = 0, NMS_interpolation = 1):
    """
    Canny 边缘检测核心算法

    img: 输入的待检测的图片
    is_bilateral:表示是否用双边滤波代替高斯滤波，默认为0，表示不代替。
    is_medium:表示是否在高斯滤波之前使用自适应中值滤波，默认为 0，表示不使用
    gausssize:高斯滤波的滤波核大小，默认3*3
    gausssigma：高斯滤波的方差，默认为1
    bilateral_size：双边滤波的滤波核大小，默认为9
    bilateral_dsigma：双边滤波的空间域sigma大小，默认30
    bilateral_rsigma：双边滤波的值域sigma大小，默认30
    sobel_direct: sobel梯度检测的算子方向数量，只能选择2、4，默认2
    thres1：双阈值检测的阈值，默认None
    thres2：双阈值检测的阈值，默认None
    otsu: 是否使用Otsu自适应检测阈值，默认0
    NMS_interpolation:是否用线性插值来NMS，默认0，表示不用

    :return: 边缘检测好的图片
    """
    if img is None:
        raise Exception('input image ERROR!')

    # 第一步：高斯滤波
    img = Gray(img)

    # 判断是否双边滤波
    if is_bilateral: # 双边滤波代替高斯滤波
        img = bilateralfilter.BilateralFilter(img, bilateral_size, bilateral_dsigma, bilateral_rsigma)
    else:
        # 判断是否加入自适应中值滤波
        if is_medium:
            img = adaptivemidfilter.adapt_mid_filter(img) # 自适应中值滤波
        img = GaussFilter(img, gausssize, gausssigma)

    # 第二步：求梯度及梯度方向（Sobel）
    derect = sobel_direct
    dx, dy, d, direct = sobel.SobelFilter(img, 3, derect) # 如果NMS不需要插值处理，则dx、dy用不上

    # 第三步：非极大值抑制 + 双阈值检测
    nmsedimage = NMS.nmsAndDualThreds(d, dx, dy, direct, FLAG=NMS_interpolation, thres1=thres1, thres2=thres2, isotsu =otsu)

    print('执行完毕：Canny算法')

    return nmsedimage

